package edu.zjucst.spb.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.zjucst.spb.dao.user.UserDao;
import edu.zjucst.spb.domain.ResponseResult;
import edu.zjucst.spb.domain.param.user.LoginParam;
import edu.zjucst.spb.domain.param.user.SignUpParam;
import edu.zjucst.spb.domain.entity.SpbUser;
import edu.zjucst.spb.domain.vo.user.LoginVO;
import edu.zjucst.spb.enums.OptStatusEnum;
import edu.zjucst.spb.enums.UserBusinessStatusEnum;
import edu.zjucst.spb.exception.UserBusinessException;
import edu.zjucst.spb.pkg.shiro.token.SPBUsernamePasswordToken;
import edu.zjucst.spb.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.flowable.engine.IdentityService;
import org.flowable.idm.api.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author qingo
 * @date 2022/12/22 16:50
 **/
@Slf4j
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, SpbUser> implements UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private IdentityService identityService;

    /**
     * 注册接口
     *
     * @author qingo
     * @date 2022/12/22 15:56
     **/
    @Transactional
    public ResponseResult<Object> signUp(SignUpParam dto) {
        // 1.1参数检验
        if (StringUtils.isEmpty(dto.getUserNumber()) || StringUtils.isEmpty(dto.getPwd())) {
            return ResponseResult.error(OptStatusEnum.PARAM_ERROR);
        }
        // 1.2 需要两次密码一致
        if (!dto.getPwdConfirmed().equals(dto.getPwd())) {
            throw new UserBusinessException(UserBusinessStatusEnum.PWD_NOT_SAME_ERR);
        }
        // 2. 创建对象
        SpbUser user = dto.transform();

        // 3.1 插入数据库 tb_user
        try {
            userDao.insert(user);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                return ResponseResult.error(OptStatusEnum.OPT_ERROR.getCode(), "账号已存在, 无法注册");
            }
        }

        // 3.2 同步操作 flowable的user表, UserEntityImpl不行
        User userIDM = identityService.newUser(String.valueOf(user.getId()));
        userIDM.setId(String.valueOf(user.getId()));
        userIDM.setDisplayName(user.getUsername());
        userIDM.setPassword(user.getPwd());
        identityService.saveUser(userIDM);
        return ResponseResult.success();
    }


    /**
     * 登录接口
     *
     * @author qingo
     * @date 2022/12/22 15:56
     **/
    public ResponseResult<LoginVO> login(LoginParam loginParam) {
        Subject subject = SecurityUtils.getSubject();

        try {
            subject.login(new SPBUsernamePasswordToken(loginParam.getUserNumber(), loginParam.getPwd()));
        } catch (UnknownAccountException e) {
            return ResponseResult.error(UserBusinessStatusEnum.USER_NOT_EXIST.getCode(), UserBusinessStatusEnum.USER_NOT_EXIST.getDescription());
        } catch (IncorrectCredentialsException e) {
            return ResponseResult.error(UserBusinessStatusEnum.PASSWORD_ERROR.getCode(), UserBusinessStatusEnum.PASSWORD_ERROR.getDescription());
        }
//        验证成功
        SpbUser spbUser = userDao.selectOne(new LambdaQueryWrapper<SpbUser>().eq(SpbUser::getUserNumber, loginParam.getUserNumber()));
        LoginVO loginVO = new LoginVO();//LoginVO包含学号userNumber、用户名username以及角色名roleName
        loginVO.setUserNumber(spbUser.getUserNumber());
        loginVO.setRoleName(spbUser.getRoleName());
        loginVO.setUsername(spbUser.getUsername());

        return ResponseResult.success(loginVO);
    }


    // TODO: 修改密码
}
